<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>let</title>
</head>
<body>
    <script>
        /**
            * let块级作用域，只有在变量定义的{}内才能访问得到
        */

            //    {
            //        let num =12;
            //    }
            //        console.log(num);//访问不到


                    /**
                     * for循环中的let(块级作用域不仅仅指的是{} 各种循环 条件表达式中定义的变量都是块级作用域
                     * 他们只能在当前的循环体中使用)
                     * */    

                    /* 每一次循环都是一个新的变量 */
                    // for(let i =0;i<10;i++){
                    //     console.log(i);
                    // }
                        // console.log(i);//超出作用域

                    //     for(var i =0;i<10;i++){
                    //     console.log(i);
                    // }
                    //     console.log(i);    

                    /*for循环还有一个特别之处，就是设置循环变量的那部分是一个父作用域，
                    而循环体内部是一个单独的子作用域*/

                    // for(let i = 1;i<5;i++){
                    //     let i=100;
                    //     console.log(i);//打印的是内部的i
                    // }
        
        
        /**
         * let定义的变量不存在变量提升
         **/            
                    
                    /*let所声明的变量一定要在声明后使用，否则报错*/

                    // console.log(a);
                    // let a = 100;

                    /*暂时性死区：在代码块内，使用let命令声明变量之前，该变量都是不可用的*/

                    // if(true){
                    //     tmp = 123;//报错
                    //     let temp;
                    // }

                    // typeof a;//报错  typeof不一定是完全安全的操作 如果该变量定义在typeof的下方就会出错
                    // let a =12;

                    /*比较隐蔽的暂时性死区*/

                    /*函数的吗默认参数定义也是类似于let,而且是从左到右执行
                      let x=y;此时y未赋值，会报错
                    */

                    // function foo1(x=y,y=100){
                    //     console.log(x,y);
                    // }
                    // //这样就不会报错了 
                    // function foo1(x=100,y=x){
                    //     console.log(x,y);
                    // }

                    // foo1();

                    // var x = x;//相当于 var x;
                    // console.log(typeof x);//undefined

                    // let x =x;//报错

        /**
         * let不允许在相同作用域内，重复声明同一个变量。*/        
           //不能在函数内部重新声明参数
           
        //    function foo(num){
        //        let num =100;//报错
        //    }

        /**
         * 块级作用域和作用域链不冲突：块级作用域指的是外部不能访问到作用域内部的变量
         * 但是在查找变量的时候还是会沿着作用域链从当前作用域域开始一层层的向上找
        */

        // if(true){
        //     let num = 100;
        //      while(1){
        //          console.log(num);//可以找到
        //      }
        // }

        // if(true){
        //     {let num = 100;}
        //      while(1){
        //          console.log(num);//找不到
        //      }
        // }

        /**块级作用域的存在不需要使用匿名函数自调用的方式来隔离变量*/
           
   </script>
</body>
</html>